/*
  XXX does not use built-in detection function! XXX
  
alert udp $EXTERNAL_NET any -> $HOME_NET 88 (msg:"EXPLOIT MIT Kerberos ASN.1 asn1_decode_generaltime uninitialized pointer reference attempt"; flow:to_server; content:"|a1 03 02 01 05 a2 03 02 01 0a|"; fast_pattern; metadata:policy balanced-ips drop, policy security-ips drop, service kerberos; reference:cve,2009-0846; reference:bugtraq,34409; classtype:attempted-admin; sid:17741; rev:1;)
*/
/*
 * Vuln Title: XXXX
 *
 * Copyright (C) 2005-2010 Sourcefire, Inc. All Rights Reserved
 *
 * Written by XXXX, Sourcefire VRT <XXXX@sourcefire.com>
 *
 * Auto-generated by XXXX
 *
 * This file may contain proprietary rules that were created, tested and
 * certified by Sourcefire, Inc. (the "VRT Certified Rules") as well as
 * rules that were created by Sourcefire and other third parties and
 * distributed under the GNU General Public License (the "GPL Rules").  The
 * VRT Certified Rules contained in this file are the property of
 * Sourcefire, Inc. Copyright 2005 Sourcefire, Inc. All Rights Reserved.
 * The GPL Rules created by Sourcefire, Inc. are the property of
 * Sourcefire, Inc. Copyright 2002-2005 Sourcefire, Inc. All Rights
 * Reserved.  All other GPL Rules are owned and copyrighted by their
 * respective owners (please see www.snort.org/contributors for a list of
 * owners and their respective copyrights).  In order to determine what
 * rules are VRT Certified Rules or GPL Rules, please refer to the VRT
 * Certified Rules License Agreement.
 */

#include "sf_snort_plugin_api.h"
#include "sf_snort_packet.h"

#include "so-util_ber.h"

//#define DEBUG 1
#ifdef DEBUG
#define DEBUG_SO(code) code
#else
#define DEBUG_SO(code)
#endif

/* declare detection functions */
int rule17741eval(void *p);

/* declare rule data structures */
/* flow:to_server; */
static FlowFlags rule17741flow0 = 
{
    FLOW_TO_SERVER
};

static RuleOption rule17741option0 =
{
    OPTION_TYPE_FLOWFLAGS,
    {
        &rule17741flow0
    }
};

// content:"|30|", depth 0, fast_pattern; 
static ContentInfo rule17741content1 = 
{
    (uint8_t *) "|30|", /* pattern (now in snort content format) */
    0, /* depth */
    0, /* offset */
    CONTENT_FAST_PATTERN|CONTENT_BUF_NORMALIZED, /* flags */
    NULL, /* holder for boyer/moore PTR */
    NULL, /* more holder info - byteform */
    0, /* byteform length */
    0 /* increment length*/
};

static RuleOption rule17741option1 = 
{
    OPTION_TYPE_CONTENT,
    {
        &rule17741content1
    }
};

/* references for sid 40001000 */
/* reference: bugtraq "34409"; */
static RuleReference rule17741ref1 = 
{
    "bugtraq", /* type */
    "34409" /* value */
};

/* reference: cve "2009-0846"; */
static RuleReference rule17741ref2 = 
{
    "cve", /* type */
    "2009-0846" /* value */
};

static RuleReference *rule17741refs[] =
{
    &rule17741ref1,
    &rule17741ref2,
    NULL
};

/* metadata for sid 40001000 */
/* metadata:service kerberos, policy balanced-ips drop, policy security-ips drop; */
static RuleMetaData rule17741service1 = 
{
    "service kerberos"
};


static RuleMetaData rule17741policy1 = 
{
    "policy balanced-ips drop"
};

static RuleMetaData rule17741policy2 = 
{
    "policy security-ips drop"
};

static RuleMetaData rule17741policy3 = 
{
    "policy max-detect-ips drop"
};

static RuleMetaData *rule17741metadata[] =
{
    &rule17741service1,
    &rule17741policy1,
    &rule17741policy2,
    &rule17741policy3,
    NULL
};

RuleOption *rule17741options[] =
{
    &rule17741option0,
    &rule17741option1,
    NULL
};

Rule rule17741 = {
   /* rule header, akin to => tcp any any -> any any */
   {
       IPPROTO_UDP, /* proto */
       "$EXTERNAL_NET", /* SRCIP     */
       "any", /* SRCPORT   */
       0, /* DIRECTION */
       "$HOME_NET", /* DSTIP     */
       "88", /* DSTPORT   */
   },
   /* metadata */
   { 
       3,  /* genid */
       17741, /* sigid */
       5, /* revision */
       "attempted-admin", /* classification */
       0,  /* hardcoded priority XXX NOT PROVIDED BY GRAMMAR YET! */
       "SERVER-OTHER MIT Kerberos ASN.1 asn1_decode_generaltime uninitialized pointer reference attempt",     /* message */
       rule17741refs /* ptr to references */
       ,rule17741metadata
   },
   rule17741options, /* ptr to rule options */
   &rule17741eval,   /* DO NOT use the built in detection function */
   0 /* am I initialized yet? */
};

/* detection functions */
int rule17741eval(void *p)
{
    const uint8_t *cursor_normal = 0, *end_of_payload;    
    SFSnortPacket *sp = (SFSnortPacket *) p;

    BER_ELEMENT ber_element;
    BER_ELEMENT req_body;
    BER_ELEMENT req_body_SEQUENCE;       
    int         ret;

    DEBUG_SO(printf("rule17741eval enter\n"));

    if(sp == NULL)
       return RULE_NOMATCH;

    // flow:to_server;
    if(checkFlow(p, rule17741options[0]->option_u.flowFlags) <= 0 )
        return RULE_NOMATCH;
        
    if (getBuffer(sp, CONTENT_BUF_NORMALIZED, &cursor_normal, &end_of_payload) <= 0)
        return RULE_NOMATCH;
  
    ret = ber_get_element(sp, cursor_normal, &ber_element);

    DEBUG_SO(printf("First element type 0x%02x\n", ber_element.type));

    if(ret < 0 || ((ber_element.type != 0x6a) && (ber_element.type != 0x6c)))
       return RULE_NOMATCH;

    // We want to delve into this element
    cursor_normal = ber_element.data.data_ptr;
 
    BER_DATA(0x30);         // SEQUENCE
    BER_SKIP(0xA1);         // pvno [1] INTEGER (5)
    BER_SKIP(0xA2);         // msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --)
    
    // if optional PA-DATA exists, skip it
    // 10 1 00011  (context-specific, structured, tag number 3)
    if (cursor_normal < end_of_payload && *cursor_normal == 0xA3)
        BER_SKIP(0xA3);     // padata [3] SEQUENCE OF PA-DATA OPTIONAL
   
    // req-body [4] KDC-REQ-BODY
    // req-body is defined as SEQUENCE and if req-body's data size is not equal to 
    // the total size of SEQUENCE, it is malicious
    
    ret = ber_get_element(sp, cursor_normal, &req_body);
    if (ret < 0)
        return RULE_NOMATCH;
    
    BER_DATA(0xA4);         

    ret = ber_get_element(sp, cursor_normal, &req_body_SEQUENCE);
    if (ret < 0)
        return RULE_NOMATCH;
 
    DEBUG_SO(printf("req_body.data_len = 0x%08x, req_body_SEQUENCE.specified_total_len = 0x%08x\n", req_body.data_len, req_body_SEQUENCE.specified_total_len);)
        
    if (req_body.data_len != req_body_SEQUENCE.specified_total_len)
        return RULE_MATCH;    
   
    return RULE_NOMATCH;
}
// #endif // 0 Don't compile the detection functions if they're not used
/*
Rule *rules[] = {
    &rule17741,
    NULL
};
*/
